//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.goldhuman.Common;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

public class TaskGraph extends com.goldhuman.Common.Runnable implements TaskState {
    private HashSet<com.goldhuman.Common.StatefulRunnable> runners = new HashSet();
    private HashSet<TaskNode> nodes = new HashSet();
    private boolean restart = false;
    private boolean stopping = false;
    private TaskNode root = null;
    com.goldhuman.Common.TaskContext context = null;
    Object locker = new Object();

    public void run() {
        if (!this.IsFinish()) {
            ThreadPool.AddTask(this);
            this.stopping = false;
        } else {
            Iterator iter;
            if (this.restart) {
                iter = this.nodes.iterator();

                while(iter.hasNext()) {
                    ((TaskNode)iter.next()).SetInit();
                }

                this.root.TurnRunning();
                this.restart = false;
                this.stopping = false;
            } else {
                iter = this.runners.iterator();

                while(iter.hasNext()) {
                    ((com.goldhuman.Common.StatefulRunnable)iter.next()).Destroy();
                }

                iter = this.nodes.iterator();

                while(iter.hasNext()) {
                    ((TaskNode)iter.next()).Destroy();
                }
            }
        }

    }

    protected TaskGraph(com.goldhuman.Common.TaskContext ctx) {
        this.root = null;
        this.context = ctx;
    }

    public boolean IsFinish() {
        synchronized(this.locker) {
            Iterator<TaskNode> iter = this.nodes.iterator();

            while(iter.hasNext()) {
                if (!((TaskNode)iter.next()).IsFinish()) {
                    return false;
                }
            }

            return true;
        }
    }

    public boolean IsStopping() {
        return this.stopping;
    }

    public void Start(TaskNode init_node) {
        this.root = init_node;
        this.root.TurnRunning();
    }

    public void Restart(TaskNode init_node) {
        this.root = init_node;
        this.restart = true;
        this.Stop();
    }

    public void Stop() {
        synchronized(this.locker) {
            Iterator<TaskNode> iter = this.nodes.iterator();

            while(iter.hasNext()) {
                ((TaskNode)iter.next()).TurnStopping();
            }

            this.stopping = true;
            ThreadPool.AddTask(this);
        }
    }

    public TaskNode CreateNode(com.goldhuman.Common.StatefulRunnable r) {
        TaskNode node = new TaskNode(r, this);
        r.graph = this;
        this.runners.add(r);
        this.nodes.add(node);
        return node;
    }

    public TaskNode CreateStopNode() {
        TaskNode node = new TaskNode((com.goldhuman.Common.StatefulRunnable)null, this);
        this.nodes.add(node);
        return node;
    }

    public TaskContext GetContext() {
        return this.context;
    }

    public void RunnableChangeState(TaskNode n) {
        if (n.GetState() == 4) {
            this.Stop();
        }

    }

    protected class TaskNode extends Runnable implements Observer {
        private HashSet<TaskNode> prev = new HashSet();
        private HashSet<TaskNode> next = new HashSet();
        private com.goldhuman.Common.StatefulRunnable task = null;
        private TaskGraph graph = null;
        private int state;

        void TurnStopping() {
            if (this.state == 1) {
                this.state = 2;
            } else if (this.state == 0) {
                this.state = 3;
            }

        }

        void SetInit() {
            this.state = 0;
            if (this.task != null) {
                this.task.Init();
            }

        }

        void TurnRunning() {
            if (this.state == 0 || this.state >= 4) {
                ThreadPool.AddTask(this);
                this.state = 1;
            }

        }

        void Destroy() {
        }

        TaskNode(StatefulRunnable _task, TaskGraph _graph) {
            this.task = _task;
            this.graph = _graph;
            this.state = 0;
            if (this.task != null) {
                this.task.Init();
                this.task.addObserver(this);
            }

        }

        public void update(Observable o, Object arg) {
            synchronized(this.graph.locker) {
                if (this.graph.IsStopping()) {
                    return;
                }

                this.state = this.task.GetState();
            }

            this.graph.RunnableChangeState(this);
            if (this.state >= 4) {
                synchronized(this.graph.locker) {
                    Iterator<TaskNode> iter = this.next.iterator();

                    while(iter.hasNext()) {
                        ((TaskNode)iter.next()).TurnRunning();
                    }
                }
            } else if (this.state == 1) {
                ThreadPool.AddTask(this);
            }

        }

        boolean IsFinish() {
            return this.state >= 4 || this.state == 3;
        }

        public int GetState() {
            return this.state;
        }

        public void run() {
            if (this.state == 2) {
                this.state = 3;
            } else if (this.state == 1) {
                synchronized(this.graph.locker) {
                    boolean prev_all_finished = true;
                    Iterator<TaskNode> iter = this.prev.iterator();

                    while(iter.hasNext()) {
                        if (!((TaskNode)iter.next()).IsFinish()) {
                            prev_all_finished = false;
                            break;
                        }
                    }

                    if (!prev_all_finished) {
                        this.state = 0;
                        return;
                    }
                }

                if (this.task != null) {
                    this.task.Run();
                    if (this.state == 1 || this.state == 2) {
                        ThreadPool.AddTask(this);
                    }
                } else {
                    this.state = 3;
                    this.graph.Stop();
                }

            }
        }

        public void AddChild(TaskNode node) {
            synchronized(this.graph.locker) {
                this.next.add(node);
                node.prev.add(this);
            }
        }
    }
}
